【buu】【另一种抽象的xxtea】[2019红帽杯]xx b题看了一整天,总算是看明白了TMD
查克无壳64位,拖入ida
发现一很大一坨代码,慢慢分析吧
有个输入函数和v6
这里的v6后面的Code不是上面要输入Code,跟进发现是另外的一串字符
这里也是要吐槽煞笔ida伪代码的反编译的表达形式
*(v9 + Code - v5)表示的code[v9-v5]
这v13是检测v6的长度
if语句是遍历检测输入的字符是否在v6的范围内,是的话就跳出循环,
如果有不属于v6的字符存在v11就会累加到36
v14这一小段也是检测v6长度
当有不属于v6的字符存在时就会退出
v9 - v5 < 4表达的是这一段代码只截取输入的前四个字符
这里v3搞错了应该是19,这里的code是输入
v30动调出来的是输入的flag的前四个字符
下面的连续的4个 if  表明前四个字符不能是0
首先这个循环是一个密钥扩展,是把输入的flag前四个字母扩展成16位,也就是4个4位的密钥
然后内个sub_7FF7ADD11AB0是比较抽象的xxtea加密,具体是用一个插件FindCrypt 和结合题目猜测可能是xxtea
Size是动调出来的是个固定值24
然后就是进行位置交换混淆
这里的异或最开始没看懂
首先是这个++v22这个v22可以认为是一个数组,++v22是指向数组的后一个元素
然后里面的if语句表示要从3开始异或,所以前三个(0-2)元素不会进行操作
当从3开始会进行异或,把当前的v22的值 与从0位置开始的v20 进行异或
每三个元素为一组,每组比上一组多进行一次异或,
多进行的那一次异或,是将刚才异或得到的值 与**v20[(刚才得值+1)]**进行异或
一直到v21 =  23进行最后一次循环
v30 v30[1] v31 v32是密文。但是要注意小端序,建议动调调到这里直接提取
综上我们先把换位混淆的密文和迭代异或先给解回去
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 #include  <iostream>  #include  <Windows.h>  using  namespace  std;int  main () 	int  mix[] = { 0xCE , 0xBC , 0x40 , 0x6B , 0x7C , 0x3A , 0x95 , 0xC0 , 0xEF , 0x9B ,    				0x20 , 0x20 , 0x91 , 0xF7 , 0x02 , 0x35 , 0x23 , 0x18 , 0x02 , 0xC8 ,    				0xE7 , 0x56 , 0x56 , 0xFA };   			   	int  enc[24 ];   	int  count = 0 ;   	   	for  (int  i = 23 ; i >=3 ; i--) 	{ 		 		for  (int  j = 6 -count; j >= 0 ; j--) 		{ 				mix[i]^=mix[j];		 		} 		if  (i % 3  == 0 ) 		{ 			count++; 		} 		 	}   	enc[2 ] = mix[0 ]; 	enc[0 ] = mix[1 ]; 	enc[3 ] = mix[2 ]; 	enc[1 ] = mix[3 ]; 	enc[6 ] = mix[4 ]; 	enc[4 ] = mix[5 ]; 	enc[7 ] = mix[6 ]; 	enc[5 ] = mix[7 ]; 	enc[10 ] = mix[8 ]; 	enc[8 ] = mix[9 ]; 	enc[11 ] = mix[10 ]; 	enc[9 ] = mix[11 ]; 	enc[14 ] = mix[12 ]; 	enc[12 ] = mix[13 ]; 	enc[15 ] = mix[14 ]; 	enc[13 ] = mix[15 ]; 	enc[18 ] = mix[16 ]; 	enc[16 ] = mix[17 ]; 	enc[19 ] = mix[18 ]; 	enc[17 ] = mix[19 ]; 	enc[22 ] = mix[20 ]; 	enc[20 ] = mix[21 ]; 	enc[23 ] = mix[22 ]; 	enc[21 ] = mix[23 ]; 	for  (int  i = 0 ; i < 24 ; i++) 		printf ("0x%x," , enc[i]);   	 	return  0 ; } 
然后再找一个xxtea脚本进行解密
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 #include  <stdio.h>  #include  <stdint.h>  #define  DELTA 0x9e3779b9 #define  MX (((z>>5^y<<2) + (y> >3^z<<4)) ^ ((sum^y) + (key[(p&3)^e] ^ z))) void  btea (uint32_t  *v, int  n, uint32_t  const  key[4 ])     uint32_t  y, z, sum;     unsigned  p, rounds, e;     if  (n > 1 )                 {         rounds = 6  + 52 /n;         sum = 0 ;         z = v[n-1 ];         do          {             sum += DELTA;             e = (sum >> 2 ) & 3 ;             for  (p=0 ; p<n-1 ; p++)             {                 y = v[p+1 ];                 z = v[p] += MX;             }             y = v[0 ];             z = v[n-1 ] += MX;         }while  (--rounds);     }     else  if  (n < -1 )           {         n = -n;         rounds = 6  + 52 /n;         sum = rounds*DELTA;         y = v[0 ];         do          {             e = (sum >> 2 ) & 3 ;             for  (p=n-1 ; p>0 ; p--)             {                 z = v[p-1 ];                 y = v[p] -= MX;             }             z = v[n-1 ];             y = v[0 ] -= MX;             sum -= DELTA;         }while  (--rounds);     } } int  main ()     uint32_t  v[6 ]= {0x40cea5bc ,0xe7b2b2f4 ,0x129d12a9 ,0x5bc810ae ,0x1d06d73d ,0xdcf870dc };     uint32_t  const  k[4 ]= {(unsigned  int )0x67616c66 ,(unsigned  int )0x0 ,(unsigned  int )0x0 ,(unsigned  int )0x0 };     int  n = 6 ;     btea (v, -n, k); 	for (int  i = 0 ; i<6  ; i++)     	printf ("%x\n" ,v[i]);     return  0 ; } 
然后把的出来的16进制转换成字符,注意小端序